<?php
namespace App\Models;

use App\Config\Database;
use PDO;
use PDOException;

/**
 * 消息模型
 * @package App\Models
 * @description:
 * 1. 保存消息
 * 2. 获取历史消息
 * 3. 标记消息为已读
 * 4. 获取未读消息数量
 * 5. 撤回消息
 * 6. 通过消息ID查询
 */
class Message{
    private $conn;
    private $table = 'messages';

    public $id;
    public $message_id;
    public $sender_id;
    public $receiver_type;
    public $receiver_id;
    public $content_type;
    public $content;
    public $status;
    public $is_read;
    public $timestamp;

    public function __construct() {
        //数据库的初始化
        $database = new Database();
        $this->conn = $database->getConnection();
    }

    /**
     * 保存消息到数据库
     * @return bool
     */
    public function save(){
        try {
            $query = "INSERT INTO " . $this->table . " 
                (message_id, sender_id, receiver_type, receiver_id, content_type, content, status, is_read, timestamp) 
                VALUES 
                (:message_id, :sender_id, :receiver_type, :receiver_id, :content_type, :content, :status, :is_read, :timestamp)";
            $stmt = $this->conn->prepare($query);

            // 绑定参数
            $stmt->bindParam(':message_id', $this->message_id);
            $stmt->bindParam(':sender_id', $this->sender_id);
            $stmt->bindParam(':receiver_type', $this->receiver_type);
            $stmt->bindParam(':receiver_id', $this->receiver_id);
            $stmt->bindParam(':content_type', $this->content_type);
            $stmt->bindParam(':content', $this->content);
            $stmt->bindParam(':status', $this->status);
            $stmt->bindParam(':is_read', $this->is_read);
            $stmt->bindParam(':timestamp', $this->timestamp);

            //设置默认值
            $this->status = 1;
            
            // 单聊这里的is_read默认为0，群聊这里的is_read不适用
            if ($this->receiver_type == 1){
                $this->is_read = 0;
            } else {
                $this->is_read = null;
            }

            return $stmt->execute();
        } catch(PDOException $e) {
            error_log("Save message error: " .$e->getMessage());
            return false;
        }
    }

    /**
     * 获取历史消息
     * @param int $userId 当前用户ID
     * @param int $receiverType 接收者类型（1-用户，2-群组）
     * @param int $receiverId 接收者ID
     * @param int|null $beforeTimestamp 时间戳（获取此时间之前的消息）
     * @param int $offset 分页偏移
     * @param int $limit 分页大小
     * @return array
     */
    public function getHistory($userId, $receiverType, $receiverId, $beforeTimestamp = null, $offset = 0, $limit = 20){
        try {
            // 构建查询条件
            $conditions = [];
            $params = [];

            // 确定是作为发送者还是接受者查询
            if ($receiverType == 1){ 
                // 这里的单聊需要获取双方的信息
                $conditions[] = "(sender_id = :user_id AND receiver_id = :receiver_id AND receiver_type = :receiver_type) 
                                OR (receiver_id = :user_id AND sender_id = :receiver_id AND receiver_type = :receiver_type)";
                $params[':user_id'] = $userId;
                $params[':receiver_id'] = $receiverId;
                $params[':receiver_type'] = $receiverType;
            } else {
                // 群聊：只查询该群组的消息
                $conditions[] = "receiver_id = :receiver_id AND receiver_type = :receiver_type";
                $params[':receiver_id'] = $receiverId;
                $params[':receiver_type'] = $receiverType;
            }

            // 时间戳条件
            if ($beforeTimestamp){
                $conditions[] = "timestamp < :before_timestamp";
                $params[':before_timestamp'] = $beforeTimestamp;
            }

            // 构建SQL查询
            $whereClause = !empty($conditions) ? "WHERE " . implode(" AND ", $conditions) : "";
            $orderBy = "ORDER BY timestamp DESC";
            $limitClause = "LIMIT :offset, :limit";
            
            // $query = "SELECT * FROM " . $this->table . " " . $whereClause . " " . $orderBy . " " . $limitClause;
            // 修改点：关联users表获取发送者详细信息
            $query = "SELECT m.*, 
                             u.id AS sender_id,
                             u.user_id AS sender_user_id, 
                             u.username AS sender_name, 
                             u.email AS sender_email,
                             u.phone AS sender_phone,
                             u.avatar_url AS sender_avatar 
                      FROM " . $this->table . " m
                      JOIN users u ON m.sender_id = u.id
                      " . $whereClause . " " . $orderBy . " " . $limitClause;
            
            $stmt = $this->conn->prepare($query);
            
            // 绑定参数
            foreach ($params as $key => $value) {
                $stmt->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
            }
            $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
            $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
            
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch(PDOException $e) {
            error_log("Get history message error: " .$e->getMessage());
            return [];
        }
    }

    /**
     * 标记单聊消息为已读
     * @param int $userId 当前用户ID（接收者）
     * @param int $senderId 发送者ID
     * @return bool
     */
    public function markAsRead($userId, $senderId) {
        try {
            $query = "UPDATE " . $this->table . " 
                      SET is_read = 1 
                      WHERE receiver_id = :user_id 
                      AND sender_id = :sender_id 
                      AND receiver_type = 1 
                      AND status = 1";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
            $stmt->bindParam(':sender_id', $senderId, PDO::PARAM_INT);
            
            return $stmt->execute();
        } catch (PDOException $e) {
            error_log("Mark as read error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 获取未读消息数量
     * @param int $userId 用户ID
     * @return array
     */
    public function getUnreadCount($userId) {
        try {
            // 获取单聊未读消息数量
            $query = "SELECT sender_id, COUNT(*) as count 
                      FROM " . $this->table . " 
                      WHERE receiver_id = :user_id 
                      AND receiver_type = 1 
                      AND is_read = 0 
                      AND status = 1 
                      GROUP BY sender_id";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
            $stmt->execute();
            $singleChatCounts = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // 转换为以sender_id为键的数组
            $result = [];
            foreach ($singleChatCounts as $item) {
                $result[$item['sender_id']] = $item['count'];
            }
            
            return $result;
        } catch (PDOException $e) {
            error_log("Get unread count error: " . $e->getMessage());
            return [];
        }
    }

    /**
     * 撤回消息
     * @param string $messageId 消息ID
     * @return bool
     */
    public function revoke($messageId) {
        try {
            $query = "UPDATE " . $this->table . " 
                      SET status = 0 
                      WHERE message_id = :message_id";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':message_id', $messageId);
            return $stmt->execute();
        } catch (PDOException $e) {
            error_log("Revoke message error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 通过消息ID查询消息
     * @param string $messageId 消息ID
     * @return array|null
     */
    public function findByMessageId($messageId) {
        try {
            $query = "SELECT * FROM " . $this->table . " WHERE message_id = :message_id LIMIT 1";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':message_id', $messageId);
            $stmt->execute();
            
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Find message by ID error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * 获取用户的单聊会话列表
     * @param int $userId 用户ID
     * @return array
     */
    public function getSingleChatConversations($userId) {
        try {
            // 查询与当前用户相关的所有单聊消息 - 修正状态条件
            $query = "SELECT m.*, 
                      CASE 
                        WHEN m.sender_id = :user_id THEN m.receiver_id 
                        ELSE m.sender_id 
                      END as contact_id
                      FROM " . $this->table . " m
                      WHERE m.receiver_type = 1 
                        AND (m.sender_id = :user_id OR m.receiver_id = :user_id)
                        AND (m.status = 1 OR m.status = 'sent')  
                      ORDER BY m.timestamp DESC";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
            $stmt->execute();
            
            $messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
            
            // 按联系人分组，获取每个联系人的最后一条消息
            $conversations = [];
            $contactIds = [];
            
            foreach ($messages as $message) {
                $contactId = $message['contact_id'];
                
                // 如果已经处理过这个联系人，跳过
                if (isset($contactIds[$contactId])) {
                    continue;
                }
                
                // 获取未读消息数量 - 修正条件
                $unreadCount = 0;
                // 修正：只对当前用户收到的消息计算未读数
                if ($message['sender_id'] != $userId) {
                    $query = "SELECT COUNT(*) as count 
                              FROM " . $this->table . " 
                              WHERE receiver_id = :user_id 
                                AND sender_id = :contact_id 
                                AND receiver_type = 1 
                                AND (is_read = 0 OR is_read IS NULL)
                                AND (status = 1 OR status = 'sent')";
                    $stmt2 = $this->conn->prepare($query);
                    $stmt2->bindParam(':user_id', $userId, PDO::PARAM_INT);
                    $stmt2->bindParam(':contact_id', $contactId, PDO::PARAM_INT);
                    $stmt2->execute();
                    $result = $stmt2->fetch(PDO::FETCH_ASSOC);
                    $unreadCount = $result['count'];
                }
                
                $conversations[] = [
                    'type' => 1,
                    'id' => $contactId,
                    'last_message_id' => $message['message_id'],
                    'content_type' => $message['content_type'],
                    'content' => $message['content'],
                    'timestamp' => $message['timestamp'],
                    'unread_count' => $unreadCount
                ];
                
                $contactIds[$contactId] = true;
            }
            
            return $conversations;
        } catch (PDOException $e) {
            error_log("Get single chat conversations error: " . $e->getMessage());
            return [];
        }
    }


    /**
     * 获取群组的最后一条消息
     * @param int $groupId 群组ID
     * @return array|null
     */
    public function getGroupLastMessage($groupId) {
        try {
            $query = "SELECT * 
                      FROM " . $this->table . " 
                      WHERE receiver_type = 2 
                        AND receiver_id = :group_id 
                        AND status = 1
                      ORDER BY timestamp DESC 
                      LIMIT 1";
            
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':group_id', $groupId, PDO::PARAM_INT);
            $stmt->execute();
            
            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Get group last message error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * 标记群消息为已读
     * @param string $messageId 消息ID
     * @param int $userId 用户ID
     * @param int $groupId 群组ID
     * @return bool
     */
    public function markGroupMessageAsRead($messageId, $userId, $groupId) {
        try {
            // 先检查是否已经标记过
            $checkQuery = "SELECT COUNT(*) as count 
                           FROM message_reads 
                           WHERE message_id = :message_id AND user_id = :user_id";
            $checkStmt = $this->conn->prepare($checkQuery);
            $checkStmt->bindParam(':message_id', $messageId);
            $checkStmt->bindParam(':user_id', $userId);
            $checkStmt->execute();
            $result = $checkStmt->fetch(PDO::FETCH_ASSOC);
            
            if ($result['count'] == 0) {
                // 如果没有标记过，则插入记录
                $insertQuery = "INSERT INTO message_reads (message_id, group_id, user_id) 
                                VALUES (:message_id, :group_id, :user_id)";
                $insertStmt = $this->conn->prepare($insertQuery);
                $insertStmt->bindParam(':message_id', $messageId);
                $insertStmt->bindParam(':group_id', $groupId);
                $insertStmt->bindParam(':user_id', $userId);
                return $insertStmt->execute();
            }
            
            return true;
        } catch (PDOException $e) {
            error_log("Mark group message as read error: " . $e->getMessage());
            return false;
        }
    }

    /**
     * 搜索消息
     * @param int $userId 当前用户ID
     * @param int|null $startTime 开始时间戳（毫秒）
     * @param int|null $endTime 结束时间戳（毫秒）
     * @param string|null $keyword 关键词
     * @param int $page 页码
     * @param int $pageSize 每页数量
     * @return array
     */
    public function searchMessages($userId, $startTime = null, $endTime = null, $keyword = null, $page = 1, $pageSize = 20) {
        try {
            $conditions = [];
            $params = [];

            // 仅查询当前用户参与的消息
            // 1. 用户是消息发送者（包括单聊和群聊）
            // 2. 用户是单聊接收者
            // 3. 用户是群组成员（不管是否是好友）
            $conditions[] = "(
                m.sender_id = :user_id 
                OR (m.receiver_id = :user_id AND m.receiver_type = 1)
                OR (m.receiver_type = 2 AND EXISTS (
                    SELECT 1 FROM group_members 
                    WHERE group_id = m.receiver_id AND user_id = :user_id
                ))
            )";
            $params[':user_id'] = $userId;

            // 时间范围条件
            if ($startTime !== null) {
                $conditions[] = "m.timestamp >= :start_time";
                $params[':start_time'] = $startTime;
            }
            if ($endTime !== null) {
                $conditions[] = "m.timestamp <= :end_time";
                $params[':end_time'] = $endTime;
            }

            // 关键词搜索条件
            if ($keyword !== null && trim($keyword) !== '') {
                $conditions[] = "m.content LIKE :keyword";
                $params[':keyword'] = '%' . trim($keyword) . '%';
            }

            // 构建查询条件
            $whereClause = !empty($conditions) ? "WHERE " . implode(" AND ", $conditions) : "";
            $orderBy = "ORDER BY m.timestamp DESC";
            $offset = ($page - 1) * $pageSize;
            $limitClause = "LIMIT :offset, :limit";

            // 关联users表获取发送者详细信息，并关联groups表获取群组信息
            $query = "SELECT m.*, 
                             u.id AS sender_id,
                             u.user_id AS sender_user_id, 
                             u.username AS sender_name, 
                             u.email AS sender_email,
                             u.phone AS sender_phone,
                             u.avatar_url AS sender_avatar,
                             -- 添加群组相关信息（仅当是群聊消息时） --
                             CASE WHEN m.receiver_type = 2 THEN g.id ELSE NULL END AS group_id,
                             CASE WHEN m.receiver_type = 2 THEN g.name ELSE NULL END AS group_name,
                             CASE WHEN m.receiver_type = 2 THEN g.avatar_url ELSE NULL END AS group_avatar,
                             CASE WHEN m.receiver_type = 2 THEN g.announcement ELSE NULL END AS group_announcement
                      FROM " . $this->table . " m
                      JOIN users u ON m.sender_id = u.id
                      -- 关联groups表获取群组信息 --
                      LEFT JOIN groups g ON (m.receiver_type = 2 AND m.receiver_id = g.id)
                      " . $whereClause . " " . $orderBy . " " . $limitClause;

            $stmt = $this->conn->prepare($query);

            // 绑定参数
            foreach ($params as $key => $value) {
                $stmt->bindValue($key, $value, is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);
            }
            $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
            $stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);

            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (PDOException $e) {
            error_log("Search messages error: " . $e->getMessage());
            return [];
        }
    }
}
?>